/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.worlds.object;

import javax.swing.SwingUtilities;
import net.worlds.WorldsException;
import net.worlds.Main;
import net.worlds.PropChangeHandler;
import net.worlds.lua.ScriptThread;
import net.worlds.ui.UI;


public class Script extends GameObject{

    private ScriptThread st;
    public boolean executingEvent = false;
    private boolean enabled = true;
    private boolean clientSide = false;
    public Script() throws WorldsException
    {
        super("Script");
        //x_;
    }
    public Script(String type) throws WorldsException
    {
        super(type);
        constructor();
    }
    private void constructor()
    {
        addPropChangeHandler("Enabled", new PropChangeHandler()
        {
            @Override
            public void handle(Object oldValue, Object value) throws WorldsException {
                Boolean v = (Boolean) value;
                enabled = v;
                if(!v && st != null)
                    st.stop();
                else if(v && inWorld)
                {
                    Runnable r = new Runnable()
                    {

                        public void run() {
                            try {
                                ((Script) instance).run();
                            } catch (WorldsException ex) {
                                throw new RuntimeException(ex);
                            }
                        }

                    };
                    Main.runInMainThread(r);
                }
            }
        });
    }
    public void stop()
    {
        if(st != null)
            st.stop();
    }
    public void addTask(Runnable r)
    {
        st.addTask(r);
    }
    public String getSource() throws WorldsException
    {
        if(tempProperties.get("Source") == null)
            return getStringProp("Source");
        else
            return tempProperties.get("Source").toString();
    }
    public void run() throws WorldsException
    {
        if(Main.loading || !enabled)
            return;
        if(Main.isClient())
        {
            GameObject parent = getParent();
            boolean isMine = getBooleanProp("ClientSide") && parent != null && ((parent instanceof Player && Main.getLocalPlayer() != null && Main.getLocalPlayer().getPlayer() == parent) || (parent instanceof Tool && parent.getParent() != null && parent.getParent().getParent() != null && parent.getParent().getParent() instanceof Player && Main.getLocalPlayer() != null && Main.getLocalPlayer().getPlayer() != null && Main.getLocalPlayer().getPlayer() == parent.getParent().getParent()));
            if(!isMine)
                return;
        }
        else if(Main.isServer())
        {
            if(getBooleanProp("ClientSide"))
                return;
        }
        if(!(this instanceof HiddenScript))
            Main.log("Running \""+toString()+"\"");
        //new Throwable().printStackTrace();
        if(st != null)
        {
            st.stop();
            st.unlinkEvents();
        }
        //st.getLuaState().currentThread.
        String source = getSource();
        st = new ScriptThread(this, Main.getScriptContext().newState(world), getFullName(), source);
        st.getLuaState().getEnvironment().rawset("script", this);
        st.start();
    }
    @Override
    public void beforeChangeWorld(net.worlds.World world)
    {
        super.beforeChangeWorld(world);
        stop();
    }
    @Override
    public void finishChangeWorld()
    {
        super.finishChangeWorld();
        if(st != null)
           st.getLuaState().getEnvironment().rawset("game", world.getRootObject());
        try {
            if(getBooleanProp("Enabled"))
            run();
        } catch (WorldsException ex) {
            ex.printStackTrace();
        }
    }
    @Override
    public void addToWorld() throws WorldsException
    {
        super.addToWorld();
        if(getBooleanProp("Enabled") && !(getParent() instanceof Tool && getParent().getParent() instanceof Inventory))
        {
            Runnable r = new Runnable()
            {

                public void run() {
                    try {
                        ((Script) instance).run();
                    } catch (WorldsException ex) {
                        throw new RuntimeException(ex);
                    }
                }

            };
            Main.runInMainThread(r);
        }
    }
    @Override
    public void destructor() throws WorldsException
    {
        if(this == UI.editScript)
            SwingUtilities.invokeLater(new Runnable()
            {
                public void run() {
                    UI.closeScript();
                }
            });
        super.destructor();
        stop();
    }
}
